iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Software Development

系統設計就像九頭蛇:打造社群網站的 30 天系列 第 29 篇

Day 29 資安不能只靠一道牆:Security Architecture

  • 分享至 

  • xImage
  •  

昨天盤點了 PokeThreads 的攻擊面,列出幾個明確的缺口:擋不住分散式的爬蟲與洗版、看不懂檔案內容、管不到內部服務之間的信任、也完全沒有「這個人能不能做這件事」的概念。

今天把這些缺口一個一個補上。

多層次資安防護(Security Architecture)示意圖

WAF:防火牆先擋

昨天提到 Rate Limiter 工作在應用層,很多攻擊卻在更早的階段就該被擋下。WAF(Web Application Firewall) 就是補這一段空隙的角色,它站在 Load Balancer 前面(或整合在其中),專門辨識已知的攻擊特徵,包括:

  • SQL Injection、XSS 這類經典注入攻擊的 Payload 特徵
  • 已知的惡意 IP、Bot 特徵(例如異常的 User-Agent、行為模式)
  • 常見掃描工具留下的請求指紋

WAF 的特性是規則導向:比對的是「已知的攻擊長什麼樣子」。

所以 WAF 對於新型態、還沒被寫進規則庫的攻擊就防護力有限,但光是擋掉大量已知攻擊手法,就能讓後面每一層省下不少負擔,這是它存在的意義。

Authentication:處理你是誰

這一段不重新推導,只做個總結,Authentication(AuthN,身份驗證——你是誰)這部分從 Day 2 就開始討論:

  • Day 2:最陽春的版本,Session 直接存在單一 Server 的 Memory 裡
  • Day 6:Server 變多之後,Session 搬進 Distributed Cache,或改用 JWT,並補上 Refresh Token 與 Token Revocation 機制

「使用者是誰」這件事目前已有一套可 Horizontal Scaling 的做法。

Authorization:判斷你能做什麼

前面 AuthN 回答的是「你是誰」。

Authorization(AuthZ,權限控管)回答的是「你能做什麼」,這是目前系統裡完全沒處理過的一塊。

舉個具體例子:Charmander 登入之後,理論上通過了 AuthN 這一關,如果他對著 DELETE /posts/456 發出 Request,而 456 其實是 Pikachu 發的貼文,系統該怎麼反應?

如果只檢查「這個 Request 有沒有帶合法的 Session/Token」,Charmander 會直接刪掉 Pikachu 的貼文,因為系統只確認了「你有登入」,卻沒確認「你有沒有權限動這篇貼文」。

最簡單的做法是 Ownership-based 檢查,在執行刪除前,多一道判斷「發出 Request 的人,是不是這篇貼文的作者,或是 Admin」。

規模再大一點,通常會走向 RBAC(Role-Based Access Control),把權限跟角色綁在一起,而不是每個操作都寫死判斷邏輯:

  • Role
    • id:BIGINT(Primary Key)
    • name:VARCHAR(30)
      • 例如 USER、MODERATOR、ADMIN,有的系統還有 SUPER_ADMIN
  • User(在 Day 2 的基礎上新增一個欄位)
    • role_id:BIGINT(Foreign Key → Role.id)

之後任何「能不能做某件事」的判斷,都可以統一問:「這個 User 的 Role,有沒有被授權執行這個操作」,而不是在程式碼裡到處散落零散的 if user.id == post.author_id。

Authorization 這層應該放在 Backend Service 內部(拿到 Request 之後、真正執行操作之前),而不是丟給 Day 14 的 API Gateway。

Gateway 知道「這是誰」,但通常不會知道每個 Service 內部具體的權限規則,那是各個 Service 自己該負責的事。

Abuse Prevention:比單純算速率更聰明一點

回到 Day 28 提到的問題,如果攻擊者把爬蟲/洗版流量分散到大量不同來源,讓每個來源看起來都「沒超過限制」,Rate Limiter 自然就失效了。

這需要更聰明的偵測邏輯,而不只是單純數 Request 次數:

  • 行為異常偵測:一個帳號平常一天發 2 篇文,突然在 5 分鐘內發了 50 篇一模一樣的內容,即使沒有任何單一 Request 超過 Rate Limit,這個模式本身就很可疑
  • 重複內容偵測:對貼文內容做 Hash 或相似度比對,抓出短時間內大量重複/近似內容的洗版行為
  • CAPTCHA:在登入、註冊、發文這類高風險操作上,針對「行為模式可疑」的來源動態要求人機驗證,而不是對所有使用者一律要求,避免讓體驗變差

這幾年「行為異常偵測」這件事,很大程度已經交給機器學習模型負責,而不是寫死一條條規則。

做法上通常是把使用者過去的行為(發文頻率、按讚模式、裝置指紋、瀏覽路徑等等)餵給模型,讓它輸出一個「這個行為像不像機器人」的分數(Bot Score),而不是簡單的「超過某個數字就擋」。

這樣的好處是能捕捉到規則寫不完、也還沒被定義過的異常模式,比較能適應攻擊手法一直在變化的現實,這跟前面 WAF 的規則導向剛好形成對比:

  • WAF 擋的是「已知長什麼樣子」的攻擊
  • AI 模型抓的是「看起來不對勁」的行為

WAF 和 AI 兩者互補。

這些機制通常會需要前面各層蒐集到的資料,也就是 Day 25 的 Observability 建立的 Logging/Metrics,這些元件正好是偵測「異常模式」所需要的原始資料來源。

現在的防護層次

把今天補上的東西疊起來,一個 Request 要真正碰到 Database 之前,會依序經過:

Client
  ↓
WAF(擋已知攻擊特徵)
  ↓
Load Balancer
  ↓
API Gateway(Auth + Rate Limiter + 濫用偵測)
  ↓
Backend Service(Authorization:這個人能做這件事嗎?)
  ↓
Database

沒有任何一層是萬能的,WAF 擋不住合法帳號的濫用行為,Rate Limiter 擋不住分散式的慢速攻擊,Authorization 管不到「還沒登入就發生」的問題。

資安防護不是一道完美的牆,而是讓每一層各自負責最擅長的那一種風險,疊加起來才夠紮實。

小結

今天把 Day 28 找出的缺口逐一補上:

  • WAF 擋在最前面過濾已知攻擊
  • Authentication 處理「你是誰」,沿用 Day 2/6 已經打好的基礎
  • Authorization 回答「這個人能不能做這件事」
  • Abuse Prevention 則靠 AI 模型判斷行為異常,處理 Rate Limiter 管不到的分散式濫用

這個系列一路把 PokeThreads 從一台 Server 做到今天,資安內容卻是第 28、29 天才認真討論,現實中絕對不能這樣搞。

在實務上,這些考量理想上應該從一開始就融入每個設計決策,而不是蓋完系統才回頭補防護,但作為一個系統設計的入門系列,先把系統做出來、理解它怎麼運作,再回頭看它哪裡會被攻破,我自己覺得是一種合理的學習順序啦,畢竟很多人對資安議題就是沒興趣 😅。

明天是這個系列的最後一篇,該回頭看看,這一路是怎麼從一台最陽春的 Server,走到今天這個樣子的。


上一篇
Day 28 Threat Modeling 研究哪裡會出包
下一篇
Day 30 從一台 Server 到今天的系統設計回顧
系列文
系統設計就像九頭蛇:打造社群網站的 30 天 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言